home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / WarpQuake / Src / r_drawa.s < prev    next >
Text File  |  2000-05-22  |  19KB  |  839 lines

  1. /*
  2. Copyright (C) 1996-1997 Id Software, Inc.
  3.  
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
  12.  
  13. See the GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. */
  20. //
  21. // r_drawa.s
  22. // x86 assembly-language edge clipping and emission code
  23. //
  24.  
  25. #include "asm_i386.h"
  26. #include "quakeasm.h"
  27. #include "asm_draw.h"
  28. #include "d_ifacea.h"
  29.  
  30. #if    id386
  31.  
  32. // !!! if these are changed, they must be changed in r_draw.c too !!!
  33. #define FULLY_CLIPPED_CACHED    0x80000000
  34. #define FRAMECOUNT_MASK            0x7FFFFFFF
  35.  
  36.     .data
  37.  
  38. Ld0:            .single        0.0
  39. Ld1:            .single        0.0
  40. Lstack:            .long        0
  41. Lfp_near_clip:    .single        NEAR_CLIP
  42. Lceilv0:        .long        0
  43. Lv:                .long        0
  44. Lu0:            .long        0
  45. Lv0:            .long        0
  46. Lzi0:            .long        0
  47.  
  48.     .text
  49.  
  50. //----------------------------------------------------------------------
  51. // edge clipping code
  52. //----------------------------------------------------------------------
  53.  
  54. #define pv0        4+12
  55. #define pv1        8+12
  56. #define clip    12+12
  57.  
  58.     .align 4
  59. .globl C(R_ClipEdge)
  60. C(R_ClipEdge):
  61.     pushl    %esi                // preserve register variables
  62.     pushl    %edi
  63.     pushl    %ebx
  64.     movl    %esp,Lstack            // for clearing the stack later
  65.  
  66. //    float        d0, d1, f;
  67. //    mvertex_t    clipvert;
  68.  
  69.     movl    clip(%esp),%ebx
  70.     movl    pv0(%esp),%esi
  71.     movl    pv1(%esp),%edx
  72.  
  73. //    if (clip)
  74. //    {
  75.     testl    %ebx,%ebx
  76.     jz        Lemit
  77.  
  78. //        do
  79. //        {
  80.  
  81. Lcliploop:
  82.  
  83. //            d0 = DotProduct (pv0->position, clip->normal) - clip->dist;
  84. //            d1 = DotProduct (pv1->position, clip->normal) - clip->dist;
  85.     flds    mv_position+0(%esi)
  86.     fmuls    cp_normal+0(%ebx)
  87.     flds    mv_position+4(%esi)
  88.     fmuls    cp_normal+4(%ebx)
  89.     flds    mv_position+8(%esi)
  90.     fmuls    cp_normal+8(%ebx)
  91.     fxch    %st(1)
  92.     faddp    %st(0),%st(2)        // d0mul2 | d0add0
  93.  
  94.     flds    mv_position+0(%edx)
  95.     fmuls    cp_normal+0(%ebx)
  96.     flds    mv_position+4(%edx)
  97.     fmuls    cp_normal+4(%ebx)
  98.     flds    mv_position+8(%edx)
  99.     fmuls    cp_normal+8(%ebx)
  100.     fxch    %st(1)
  101.     faddp    %st(0),%st(2)        // d1mul2 | d1add0 | d0mul2 | d0add0
  102.     fxch    %st(3)                // d0add0 | d1add0 | d0mul2 | d1mul2
  103.  
  104.     faddp    %st(0),%st(2)        // d1add0 | dot0 | d1mul2 
  105.     faddp    %st(0),%st(2)        // dot0 | dot1
  106.  
  107.     fsubs    cp_dist(%ebx)        // d0 | dot1
  108.     fxch    %st(1)                // dot1 | d0
  109.     fsubs    cp_dist(%ebx)        // d1 | d0
  110.     fxch    %st(1)
  111.     fstps    Ld0
  112.     fstps    Ld1
  113.  
  114. //            if (d0 >= 0)
  115. //            {
  116.     movl    Ld0,%eax
  117.     movl    Ld1,%ecx
  118.     orl        %eax,%ecx
  119.     js        Lp2
  120.  
  121. // both points are unclipped
  122.  
  123. Lcontinue:
  124.  
  125. //
  126. //                R_ClipEdge (&clipvert, pv1, clip->next);
  127. //                return;
  128. //            }
  129. //        } while ((clip = clip->next) != NULL);
  130.     movl    cp_next(%ebx),%ebx
  131.     testl    %ebx,%ebx
  132.     jnz        Lcliploop
  133.  
  134. //    }
  135.  
  136. //// add the edge
  137. //    R_EmitEdge (pv0, pv1);
  138. Lemit:
  139.  
  140. //
  141. // set integer rounding to ceil mode, set to single precision
  142. //
  143. // FIXME: do away with by manually extracting integers from floats?
  144. // FIXME: set less often
  145.     fldcw    ceil_cw
  146.  
  147. //    edge_t    *edge, *pcheck;
  148. //    int        u_check;
  149. //    float    u, u_step;
  150. //    vec3_t    local, transformed;
  151. //    float    *world;
  152. //    int        v, v2, ceilv0;
  153. //    float    scale, lzi0, u0, v0;
  154. //    int        side;
  155.  
  156. //    if (r_lastvertvalid)
  157. //    {
  158.     cmpl    $0,C(r_lastvertvalid)
  159.     jz        LCalcFirst
  160.  
  161. //        u0 = r_u1;
  162. //        v0 = r_v1;
  163. //        lzi0 = r_lzi1;
  164. //        ceilv0 = r_ceilv1;
  165.     movl    C(r_lzi1),%eax
  166.     movl    C(r_u1),%ecx
  167.     movl    %eax,Lzi0
  168.     movl    %ecx,Lu0
  169.     movl    C(r_v1),%ecx
  170.     movl    C(r_ceilv1),%eax
  171.     movl    %ecx,Lv0
  172.     movl    %eax,Lceilv0
  173.     jmp        LCalcSecond
  174.  
  175. //    }
  176.  
  177. LCalcFirst:
  178.  
  179. //    else
  180. //    {
  181. //        world = &pv0->position[0];
  182.  
  183.     call    LTransformAndProject    // v0 | lzi0 | u0
  184.  
  185.     fsts    Lv0
  186.     fxch    %st(2)                    // u0 | lzi0 | v0
  187.     fstps    Lu0                        // lzi0 | v0
  188.     fstps    Lzi0                    // v0
  189.  
  190. //        ceilv0 = (int)(v0 - 2000) + 2000; // ceil(v0);
  191.     fistpl    Lceilv0
  192.  
  193. //    }
  194.  
  195. LCalcSecond:
  196.  
  197. //    world = &pv1->position[0];
  198.     movl    %edx,%esi
  199.  
  200.     call    LTransformAndProject    // v1 | lzi1 | u1
  201.  
  202.     flds    Lu0                        // u0 | v1 | lzi1 | u1
  203.     fxch    %st(3)                    // u1 | v1 | lzi1 | u0
  204.     flds    Lzi0                    // lzi0 | u1 | v1 | lzi1 | u0
  205.     fxch    %st(3)                    // lzi1 | u1 | v1 | lzi0 | u0
  206.     flds    Lv0                        // v0 | lzi1 | u1 | v1 | lzi0 | u0
  207.     fxch    %st(3)                    // v1 | lzi1 | u1 | v0 | lzi0 | u0
  208.  
  209. //    r_ceilv1 = (int)(r_v1 - 2000) + 2000; // ceil(r_v1);
  210.     fistl    C(r_ceilv1)
  211.  
  212.     fldcw    single_cw                // put back normal floating-point state
  213.  
  214.     fsts    C(r_v1)
  215.     fxch    %st(4)                    // lzi0 | lzi1 | u1 | v0 | v1 | u0
  216.  
  217. //    if (r_lzi1 > lzi0)
  218. //        lzi0 = r_lzi1;
  219.     fcom    %st(1)
  220.     fnstsw    %ax
  221.     testb    $1,%ah
  222.     jz        LP0
  223.     fstp    %st(0)
  224.     fld        %st(0)
  225. LP0:
  226.  
  227.     fxch    %st(1)                    // lzi1 | lzi0 | u1 | v0 | v1 | u0
  228.     fstps    C(r_lzi1)                // lzi0 | u1 | v0 | v1 | u0
  229.     fxch    %st(1)
  230.     fsts    C(r_u1)
  231.     fxch    %st(1)
  232.  
  233. //    if (lzi0 > r_nearzi)    // for mipmap finding
  234. //        r_nearzi = lzi0;
  235.     fcoms    C(r_nearzi)
  236.     fnstsw    %ax
  237.     testb    $0x45,%ah
  238.     jnz        LP1
  239.     fsts    C(r_nearzi)
  240. LP1:
  241.  
  242. // // for right edges, all we want is the effect on 1/z
  243. //    if (r_nearzionly)
  244. //        return;
  245.     movl    C(r_nearzionly),%eax
  246.     testl    %eax,%eax
  247.     jz        LP2
  248. LPop5AndDone:
  249.     movl    C(cacheoffset),%eax
  250.     movl    C(r_framecount),%edx
  251.     cmpl    $0x7FFFFFFF,%eax
  252.     jz        LDoPop
  253.     andl    $(FRAMECOUNT_MASK),%edx
  254.     orl        $(FULLY_CLIPPED_CACHED),%edx
  255.     movl    %edx,C(cacheoffset)
  256.  
  257. LDoPop:
  258.     fstp    %st(0)            // u1 | v0 | v1 | u0
  259.     fstp    %st(0)            // v0 | v1 | u0
  260.     fstp    %st(0)            // v1 | u0
  261.     fstp    %st(0)            // u0
  262.     fstp    %st(0)
  263.     jmp        Ldone
  264.  
  265. LP2:
  266.  
  267. // // create the edge
  268. //    if (ceilv0 == r_ceilv1)
  269. //        return;        // horizontal edge
  270.     movl    Lceilv0,%ebx
  271.     movl    C(edge_p),%edi
  272.     movl    C(r_ceilv1),%ecx
  273.     movl    %edi,%edx
  274.     movl    C(r_pedge),%esi
  275.     addl    $(et_size),%edx
  276.     cmpl    %ecx,%ebx
  277.     jz        LPop5AndDone
  278.  
  279.     movl    C(r_pedge),%eax
  280.     movl    %eax,et_owner(%edi)
  281.  
  282. //    side = ceilv0 > r_ceilv1;
  283. //
  284. //    edge->nearzi = lzi0;
  285.     fstps    et_nearzi(%edi)        // u1 | v0 | v1 | u0
  286.  
  287. //    if (side == 1)
  288. //    {
  289.     jc        LSide0
  290.  
  291. LSide1:
  292.  
  293. //    // leading edge (go from p2 to p1)
  294.  
  295. //        u_step = ((u0 - r_u1) / (v0 - r_v1));
  296.     fsubrp    %st(0),%st(3)        // v0 | v1 | u0-u1
  297.     fsub    %st(1),%st(0)        // v0-v1 | v1 | u0-u1
  298.     fdivrp    %st(0),%st(2)        // v1 | ustep
  299.  
  300. //    r_emitted = 1;
  301.     movl    $1,C(r_emitted)
  302.  
  303. //    edge = edge_p++;
  304.     movl    %edx,C(edge_p)
  305.  
  306. // pretouch next edge
  307.     movl    (%edx),%eax
  308.  
  309. //        v2 = ceilv0 - 1;
  310. //        v = r_ceilv1;
  311.     movl    %ecx,%eax
  312.     leal    -1(%ebx),%ecx
  313.     movl    %eax,%ebx
  314.  
  315. //        edge->surfs[0] = 0;
  316. //        edge->surfs[1] = surface_p - surfaces;
  317.     movl    C(surface_p),%eax
  318.     movl    C(surfaces),%esi
  319.     subl    %edx,%edx
  320.     subl    %esi,%eax
  321.     shrl    $(SURF_T_SHIFT),%eax
  322.     movl    %edx,et_surfs(%edi)
  323.     movl    %eax,et_surfs+2(%edi)
  324.  
  325.     subl    %esi,%esi
  326.  
  327. //        u = r_u1 + ((float)v - r_v1) * u_step;
  328.     movl    %ebx,Lv
  329.     fildl    Lv                    // v | v1 | ustep
  330.     fsubp    %st(0),%st(1)        // v-v1 | ustep
  331.     fmul    %st(1),%st(0)        // (v-v1)*ustep | ustep
  332.     fadds    C(r_u1)                // u | ustep
  333.  
  334.     jmp        LSideDone
  335.  
  336. //    }
  337.  
  338. LSide0:
  339.  
  340. //    else
  341. //    {
  342. //    // trailing edge (go from p1 to p2)
  343.  
  344. //        u_step = ((r_u1 - u0) / (r_v1 - v0));
  345.     fsub    %st(3),%st(0)        // u1-u0 | v0 | v1 | u0
  346.     fxch    %st(2)                // v1 | v0 | u1-u0 | u0
  347.     fsub    %st(1),%st(0)        // v1-v0 | v0 | u1-u0 | u0
  348.     fdivrp    %st(0),%st(2)        // v0 | ustep | u0
  349.  
  350. //    r_emitted = 1;
  351.     movl    $1,C(r_emitted)
  352.  
  353. //    edge = edge_p++;
  354.     movl    %edx,C(edge_p)
  355.  
  356. // pretouch next edge
  357.     movl    (%edx),%eax
  358.  
  359. //        v = ceilv0;
  360. //        v2 = r_ceilv1 - 1;
  361.     decl    %ecx
  362.  
  363. //        edge->surfs[0] = surface_p - surfaces;
  364. //        edge->surfs[1] = 0;
  365.     movl    C(surface_p),%eax
  366.     movl    C(surfaces),%esi
  367.     subl    %edx,%edx
  368.     subl    %esi,%eax
  369.     shrl    $(SURF_T_SHIFT),%eax
  370.     movl    %edx,et_surfs+2(%edi)
  371.     movl    %eax,et_surfs(%edi)
  372.  
  373.     movl    $1,%esi
  374.  
  375. //        u = u0 + ((float)v - v0) * u_step;
  376.     movl    %ebx,Lv
  377.     fildl    Lv                    // v | v0 | ustep | u0
  378.     fsubp    %st(0),%st(1)        // v-v0 | ustep | u0
  379.     fmul    %st(1),%st(0)        // (v-v0)*ustep | ustep | u0
  380.     faddp    %st(0),%st(2)        // ustep | u
  381.     fxch    %st(1)                // u | ustep
  382.  
  383. //    }
  384.  
  385. LSideDone:
  386.  
  387. //    edge->u_step = u_step*0x100000;
  388. //    edge->u = u*0x100000 + 0xFFFFF;
  389.  
  390.     fmuls    fp_1m                // u*0x100000 | ustep
  391.     fxch    %st(1)                // ustep | u*0x100000
  392.     fmuls    fp_1m                // ustep*0x100000 | u*0x100000
  393.     fxch    %st(1)                // u*0x100000 | ustep*0x100000
  394.     fadds    fp_1m_minus_1        // u*0x100000 + 0xFFFFF | ustep*0x100000
  395.     fxch    %st(1)                // ustep*0x100000 | u*0x100000 + 0xFFFFF
  396.     fistpl    et_u_step(%edi)        // u*0x100000 + 0xFFFFF
  397.     fistpl    et_u(%edi)
  398.  
  399. // // we need to do this to avoid stepping off the edges if a very nearly
  400. // // horizontal edge is less than epsilon above a scan, and numeric error
  401. // // causes it to incorrectly extend to the scan, and the extension of the
  402. // // line goes off the edge of the screen
  403. // // FIXME: is this actually needed?
  404. //    if (edge->u < r_refdef.vrect_x_adj_shift20)
  405. //        edge->u = r_refdef.vrect_x_adj_shift20;
  406. //    if (edge->u > r_refdef.vrectright_adj_shift20)
  407. //        edge->u = r_refdef.vrectright_adj_shift20;
  408.     movl    et_u(%edi),%eax
  409.     movl    C(r_refdef)+rd_vrect_x_adj_shift20,%edx
  410.     cmpl    %edx,%eax
  411.     jl        LP4
  412.     movl    C(r_refdef)+rd_vrectright_adj_shift20,%edx
  413.     cmpl    %edx,%eax
  414.     jng        LP5
  415. LP4:
  416.     movl    %edx,et_u(%edi)
  417.     movl    %edx,%eax
  418. LP5:
  419.  
  420. // // sort the edge in normally
  421. //    u_check = edge->u;
  422. //
  423. //    if (edge->surfs[0])
  424. //        u_check++;    // sort trailers after leaders
  425.     addl    %esi,%eax
  426.  
  427. //    if (!newedges[v] || newedges[v]->u >= u_check)
  428. //    {
  429.     movl    C(newedges)(,%ebx,4),%esi
  430.     testl    %esi,%esi
  431.     jz        LDoFirst
  432.     cmpl    %eax,et_u(%esi)
  433.     jl        LNotFirst
  434. LDoFirst:
  435.  
  436. //        edge->next = newedges[v];
  437. //        newedges[v] = edge;
  438.     movl    %esi,et_next(%edi)
  439.     movl    %edi,C(newedges)(,%ebx,4)
  440.  
  441.     jmp        LSetRemove
  442.  
  443. //    }
  444.  
  445. LNotFirst:
  446.  
  447. //    else
  448. //    {
  449. //        pcheck = newedges[v];
  450. //
  451. //        while (pcheck->next && pcheck->next->u < u_check)
  452. //            pcheck = pcheck->next;
  453. LFindInsertLoop:
  454.     movl    %esi,%edx
  455.     movl    et_next(%esi),%esi
  456.     testl    %esi,%esi
  457.     jz        LInsertFound
  458.     cmpl    %eax,et_u(%esi)
  459.     jl        LFindInsertLoop
  460.  
  461. LInsertFound:
  462.  
  463. //        edge->next = pcheck->next;
  464. //        pcheck->next = edge;
  465.     movl    %esi,et_next(%edi)
  466.     movl    %edi,et_next(%edx)
  467.  
  468. //    }
  469.  
  470. LSetRemove:
  471.  
  472. //    edge->nextremove = removeedges[v2];
  473. //    removeedges[v2] = edge;
  474.     movl    C(removeedges)(,%ecx,4),%eax
  475.     movl    %edi,C(removeedges)(,%ecx,4)
  476.     movl    %eax,et_nextremove(%edi)
  477.  
  478. Ldone:
  479.     movl    Lstack,%esp            // clear temporary variables from stack
  480.  
  481.     popl    %ebx                // restore register variables
  482.     popl    %edi
  483.     popl    %esi
  484.     ret
  485.  
  486. // at least one point is clipped
  487.  
  488. Lp2:
  489.     testl    %eax,%eax
  490.     jns        Lp1
  491.  
  492. //            else
  493. //            {
  494. //            // point 0 is clipped
  495.  
  496. //                if (d1 < 0)
  497. //                {
  498.     movl    Ld1,%eax
  499.     testl    %eax,%eax
  500.     jns        Lp3
  501.  
  502. //                // both points are clipped
  503. //                // we do cache fully clipped edges
  504. //                    if (!leftclipped)
  505.     movl    C(r_leftclipped),%eax
  506.     movl    C(r_pedge),%ecx
  507.     testl    %eax,%eax
  508.     jnz        Ldone
  509.  
  510. //                        r_pedge->framecount = r_framecount;
  511.     movl    C(r_framecount),%eax
  512.     andl    $(FRAMECOUNT_MASK),%eax
  513.     orl        $(FULLY_CLIPPED_CACHED),%eax
  514.     movl    %eax,C(cacheoffset)
  515.  
  516. //                    return;
  517.     jmp        Ldone
  518.  
  519. //                }
  520.  
  521. Lp1:
  522.  
  523. //            // point 0 is unclipped
  524. //                if (d1 >= 0)
  525. //                {
  526. //                // both points are unclipped
  527. //                    continue;
  528.  
  529. //            // only point 1 is clipped
  530.  
  531. //                f = d0 / (d0 - d1);
  532.     flds    Ld0
  533.     flds    Ld1
  534.     fsubr    %st(1),%st(0)
  535.  
  536. //            // we don't cache partially clipped edges
  537.     movl    $0x7FFFFFFF,C(cacheoffset)
  538.  
  539.     fdivrp    %st(0),%st(1)
  540.  
  541.     subl    $(mv_size),%esp            // allocate space for clipvert
  542.  
  543. //                clipvert.position[0] = pv0->position[0] +
  544. //                        f * (pv1->position[0] - pv0->position[0]);
  545. //                clipvert.position[1] = pv0->position[1] +
  546. //                        f * (pv1->position[1] - pv0->position[1]);
  547. //                clipvert.position[2] = pv0->position[2] +
  548. //                        f * (pv1->position[2] - pv0->position[2]);
  549.     flds    mv_position+8(%edx)
  550.     fsubs    mv_position+8(%esi)
  551.     flds    mv_position+4(%edx)
  552.     fsubs    mv_position+4(%esi)
  553.     flds    mv_position+0(%edx)
  554.     fsubs    mv_position+0(%esi)        // 0 | 1 | 2
  555.  
  556. // replace pv1 with the clip point
  557.     movl    %esp,%edx
  558.     movl    cp_leftedge(%ebx),%eax
  559.     testb    %al,%al
  560.  
  561.     fmul    %st(3),%st(0)
  562.     fxch    %st(1)                    // 1 | 0 | 2
  563.     fmul    %st(3),%st(0)
  564.     fxch    %st(2)                    // 2 | 0 | 1
  565.     fmulp    %st(0),%st(3)            // 0 | 1 | 2
  566.     fadds    mv_position+0(%esi)
  567.     fxch    %st(1)                    // 1 | 0 | 2
  568.     fadds    mv_position+4(%esi)
  569.     fxch    %st(2)                    // 2 | 0 | 1
  570.     fadds    mv_position+8(%esi)
  571.     fxch    %st(1)                    // 0 | 2 | 1
  572.     fstps    mv_position+0(%esp)        // 2 | 1
  573.     fstps    mv_position+8(%esp)        // 1
  574.     fstps    mv_position+4(%esp)
  575.  
  576. //                if (clip->leftedge)
  577. //                {
  578.     jz        Ltestright
  579.  
  580. //                    r_leftclipped = true;
  581. //                    r_leftexit = clipvert;
  582.     movl    $1,C(r_leftclipped)
  583.     movl    mv_position+0(%esp),%eax
  584.     movl    %eax,C(r_leftexit)+mv_position+0
  585.     movl    mv_position+4(%esp),%eax
  586.     movl    %eax,C(r_leftexit)+mv_position+4
  587.     movl    mv_position+8(%esp),%eax
  588.     movl    %eax,C(r_leftexit)+mv_position+8
  589.  
  590.     jmp        Lcontinue
  591.  
  592. //                }
  593.  
  594. Ltestright:
  595. //                else if (clip->rightedge)
  596. //                {
  597.     testb    %ah,%ah
  598.     jz        Lcontinue
  599.  
  600. //                    r_rightclipped = true;
  601. //                    r_rightexit = clipvert;
  602.     movl    $1,C(r_rightclipped)
  603.     movl    mv_position+0(%esp),%eax
  604.     movl    %eax,C(r_rightexit)+mv_position+0
  605.     movl    mv_position+4(%esp),%eax
  606.     movl    %eax,C(r_rightexit)+mv_position+4
  607.     movl    mv_position+8(%esp),%eax
  608.     movl    %eax,C(r_rightexit)+mv_position+8
  609.  
  610. //                }
  611. //
  612. //                R_ClipEdge (pv0, &clipvert, clip->next);
  613. //                return;
  614. //            }
  615.     jmp        Lcontinue
  616.  
  617. //            }
  618.  
  619. Lp3:
  620.  
  621. //            // only point 0 is clipped
  622. //                r_lastvertvalid = false;
  623.  
  624.     movl    $0,C(r_lastvertvalid)
  625.  
  626. //                f = d0 / (d0 - d1);
  627.     flds    Ld0
  628.     flds    Ld1
  629.     fsubr    %st(1),%st(0)
  630.  
  631. //            // we don't cache partially clipped edges
  632.     movl    $0x7FFFFFFF,C(cacheoffset)
  633.  
  634.     fdivrp    %st(0),%st(1)
  635.  
  636.     subl    $(mv_size),%esp            // allocate space for clipvert
  637.  
  638. //                clipvert.position[0] = pv0->position[0] +
  639. //                        f * (pv1->position[0] - pv0->position[0]);
  640. //                clipvert.position[1] = pv0->position[1] +
  641. //                        f * (pv1->position[1] - pv0->position[1]);
  642. //                clipvert.position[2] = pv0->position[2] +
  643. //                        f * (pv1->position[2] - pv0->position[2]);
  644.     flds    mv_position+8(%edx)
  645.     fsubs    mv_position+8(%esi)
  646.     flds    mv_position+4(%edx)
  647.     fsubs    mv_position+4(%esi)
  648.     flds    mv_position+0(%edx)
  649.     fsubs    mv_position+0(%esi)        // 0 | 1 | 2
  650.  
  651.     movl    cp_leftedge(%ebx),%eax
  652.     testb    %al,%al
  653.  
  654.     fmul    %st(3),%st(0)
  655.     fxch    %st(1)                    // 1 | 0 | 2
  656.     fmul    %st(3),%st(0)
  657.     fxch    %st(2)                    // 2 | 0 | 1
  658.     fmulp    %st(0),%st(3)            // 0 | 1 | 2
  659.     fadds    mv_position+0(%esi)
  660.     fxch    %st(1)                    // 1 | 0 | 2
  661.     fadds    mv_position+4(%esi)
  662.     fxch    %st(2)                    // 2 | 0 | 1
  663.     fadds    mv_position+8(%esi)
  664.     fxch    %st(1)                    // 0 | 2 | 1
  665.     fstps    mv_position+0(%esp)        // 2 | 1
  666.     fstps    mv_position+8(%esp)        // 1
  667.     fstps    mv_position+4(%esp)
  668.  
  669. // replace pv0 with the clip point
  670.     movl    %esp,%esi
  671.  
  672. //                if (clip->leftedge)
  673. //                {
  674.     jz        Ltestright2
  675.  
  676. //                    r_leftclipped = true;
  677. //                    r_leftenter = clipvert;
  678.     movl    $1,C(r_leftclipped)
  679.     movl    mv_position+0(%esp),%eax
  680.     movl    %eax,C(r_leftenter)+mv_position+0
  681.     movl    mv_position+4(%esp),%eax
  682.     movl    %eax,C(r_leftenter)+mv_position+4
  683.     movl    mv_position+8(%esp),%eax
  684.     movl    %eax,C(r_leftenter)+mv_position+8
  685.  
  686.     jmp        Lcontinue
  687.  
  688. //                }
  689.  
  690. Ltestright2:
  691. //                else if (clip->rightedge)
  692. //                {
  693.     testb    %ah,%ah
  694.     jz        Lcontinue
  695.  
  696. //                    r_rightclipped = true;
  697. //                    r_rightenter = clipvert;
  698.     movl    $1,C(r_rightclipped)
  699.     movl    mv_position+0(%esp),%eax
  700.     movl    %eax,C(r_rightenter)+mv_position+0
  701.     movl    mv_position+4(%esp),%eax
  702.     movl    %eax,C(r_rightenter)+mv_position+4
  703.     movl    mv_position+8(%esp),%eax
  704.     movl    %eax,C(r_rightenter)+mv_position+8
  705.  
  706. //                }
  707.     jmp        Lcontinue
  708.  
  709. // %esi = vec3_t point to transform and project
  710. // %edx preserved
  711. LTransformAndProject:
  712.  
  713. //    // transform and project
  714. //        VectorSubtract (world, modelorg, local);
  715.     flds    mv_position+0(%esi)
  716.     fsubs    C(modelorg)+0
  717.     flds    mv_position+4(%esi)
  718.     fsubs    C(modelorg)+4
  719.     flds    mv_position+8(%esi)    
  720.     fsubs    C(modelorg)+8
  721.     fxch    %st(2)                // local[0] | local[1] | local[2]
  722.  
  723. //        TransformVector (local, transformed);
  724. //    
  725. //        if (transformed[2] < NEAR_CLIP)
  726. //            transformed[2] = NEAR_CLIP;
  727. //    
  728. //        lzi0 = 1.0 / transformed[2];
  729.     fld        %st(0)                // local[0] | local[0] | local[1] | local[2]
  730.     fmuls    C(vpn)+0            // zm0 | local[0] | local[1] | local[2]
  731.     fld        %st(1)                // local[0] | zm0 | local[0] | local[1] |
  732.                                 //  local[2]
  733.     fmuls    C(vright)+0            // xm0 | zm0 | local[0] | local[1] | local[2]
  734.     fxch    %st(2)                // local[0] | zm0 | xm0 | local[1] | local[2]
  735.     fmuls    C(vup)+0            // ym0 |  zm0 | xm0 | local[1] | local[2]
  736.     fld        %st(3)                // local[1] | ym0 |  zm0 | xm0 | local[1] |
  737.                                 //  local[2]
  738.     fmuls    C(vpn)+4            // zm1 | ym0 | zm0 | xm0 | local[1] |
  739.                                 //  local[2]
  740.     fld        %st(4)                // local[1] | zm1 | ym0 | zm0 | xm0 |
  741.                                 //  local[1] | local[2]
  742.     fmuls    C(vright)+4            // xm1 | zm1 | ym0 |  zm0 | xm0 |
  743.                                 //  local[1] | local[2]
  744.     fxch    %st(5)                // local[1] | zm1 | ym0 | zm0 | xm0 |
  745.                                 //  xm1 | local[2]
  746.     fmuls    C(vup)+4            // ym1 | zm1 | ym0 | zm0 | xm0 |
  747.                                 //  xm1 | local[2]
  748.     fxch    %st(1)                // zm1 | ym1 | ym0 | zm0 | xm0 |
  749.                                 //  xm1 | local[2]
  750.     faddp    %st(0),%st(3)        // ym1 | ym0 | zm2 | xm0 | xm1 | local[2]
  751.     fxch    %st(3)                // xm0 | ym0 | zm2 | ym1 | xm1 | local[2]
  752.     faddp    %st(0),%st(4)        // ym0 | zm2 | ym1 | xm2 | local[2]
  753.     faddp    %st(0),%st(2)        // zm2 | ym2 | xm2 | local[2]
  754.     fld        %st(3)                // local[2] | zm2 | ym2 | xm2 | local[2]
  755.     fmuls    C(vpn)+8            // zm3 | zm2 | ym2 | xm2 | local[2]
  756.     fld        %st(4)                // local[2] | zm3 | zm2 | ym2 | xm2 | local[2]
  757.     fmuls    C(vright)+8            // xm3 | zm3 | zm2 | ym2 | xm2 | local[2]
  758.     fxch    %st(5)                // local[2] | zm3 | zm2 | ym2 | xm2 | xm3
  759.     fmuls    C(vup)+8            // ym3 | zm3 | zm2 | ym2 | xm2 | xm3
  760.     fxch    %st(1)                // zm3 | ym3 | zm2 | ym2 | xm2 | xm3
  761.     faddp    %st(0),%st(2)        // ym3 | zm4 | ym2 | xm2 | xm3
  762.     fxch    %st(4)                // xm3 | zm4 | ym2 | xm2 | ym3
  763.     faddp    %st(0),%st(3)        // zm4 | ym2 | xm4 | ym3
  764.     fxch    %st(1)                // ym2 | zm4 | xm4 | ym3
  765.     faddp    %st(0),%st(3)        // zm4 | xm4 | ym4
  766.  
  767.     fcoms    Lfp_near_clip
  768.     fnstsw    %ax
  769.     testb    $1,%ah
  770.     jz        LNoClip
  771.     fstp    %st(0)
  772.     flds    Lfp_near_clip
  773.  
  774. LNoClip:
  775.  
  776.     fdivrs    float_1                // lzi0 | x | y
  777.     fxch    %st(1)                // x | lzi0 | y
  778.  
  779. //    // FIXME: build x/yscale into transform?
  780. //        scale = xscale * lzi0;
  781. //        u0 = (xcenter + scale*transformed[0]);
  782.     flds    C(xscale)            // xscale | x | lzi0 | y
  783.     fmul    %st(2),%st(0)        // scale | x | lzi0 | y
  784.     fmulp    %st(0),%st(1)        // scale*x | lzi0 | y
  785.     fadds    C(xcenter)            // u0 | lzi0 | y
  786.  
  787. //        if (u0 < r_refdef.fvrectx_adj)
  788. //            u0 = r_refdef.fvrectx_adj;
  789. //        if (u0 > r_refdef.fvrectright_adj)
  790. //            u0 = r_refdef.fvrectright_adj;
  791. // FIXME: use integer compares of floats?
  792.     fcoms    C(r_refdef)+rd_fvrectx_adj
  793.     fnstsw    %ax
  794.     testb    $1,%ah
  795.     jz        LClampP0
  796.     fstp    %st(0)
  797.     flds    C(r_refdef)+rd_fvrectx_adj
  798. LClampP0:
  799.     fcoms    C(r_refdef)+rd_fvrectright_adj
  800.     fnstsw    %ax
  801.     testb    $0x45,%ah
  802.     jnz        LClampP1
  803.     fstp    %st(0)
  804.     flds    C(r_refdef)+rd_fvrectright_adj
  805. LClampP1:
  806.  
  807.     fld        %st(1)                // lzi0 | u0 | lzi0 | y
  808.  
  809. //        scale = yscale * lzi0;
  810. //        v0 = (ycenter - scale*transformed[1]);
  811.     fmuls    C(yscale)            // scale | u0 | lzi0 | y
  812.     fmulp    %st(0),%st(3)        // u0 | lzi0 | scale*y
  813.     fxch    %st(2)                // scale*y | lzi0 | u0
  814.     fsubrs    C(ycenter)            // v0 | lzi0 | u0
  815.  
  816. //        if (v0 < r_refdef.fvrecty_adj)
  817. //            v0 = r_refdef.fvrecty_adj;
  818. //        if (v0 > r_refdef.fvrectbottom_adj)
  819. //            v0 = r_refdef.fvrectbottom_adj;
  820. // FIXME: use integer compares of floats?
  821.     fcoms    C(r_refdef)+rd_fvrecty_adj
  822.     fnstsw    %ax
  823.     testb    $1,%ah
  824.     jz        LClampP2
  825.     fstp    %st(0)
  826.     flds    C(r_refdef)+rd_fvrecty_adj
  827. LClampP2:
  828.     fcoms    C(r_refdef)+rd_fvrectbottom_adj
  829.     fnstsw    %ax
  830.     testb    $0x45,%ah
  831.     jnz        LClampP3
  832.     fstp    %st(0)
  833.     flds    C(r_refdef)+rd_fvrectbottom_adj
  834. LClampP3:
  835.     ret
  836.  
  837. #endif    // id386
  838.  
  839.